import fs from "fs/promises";
import path from "path";

/**
 * Manages file hash caching for incremental indexing
 */
export class CacheManager {
  private cache: Record<string, string> = {};
  private cacheFilePath: string;

  constructor(workspacePath: string) {
    // Create cache file path in the workspace's .mcp directory
    this.cacheFilePath = path.join(workspacePath, '.mcp', 'file-hashes.json');
  }

  /**
   * Loads the cache from disk
   */
  async loadCache(): Promise<void> {
    try {
      // Ensure the .mcp directory exists
      const cacheDir = path.dirname(this.cacheFilePath);
      await fs.mkdir(cacheDir, { recursive: true });

      // Try to read the cache file
      const cacheContent = await fs.readFile(this.cacheFilePath, 'utf-8');
      this.cache = JSON.parse(cacheContent);
    } catch (error) {
      // Cache file doesn't exist or is invalid, start with empty cache
      this.cache = {};
    }
  }

  /**
   * Saves the cache to disk
   */
  async saveCache(): Promise<void> {
    try {
      const cacheDir = path.dirname(this.cacheFilePath);
      await fs.mkdir(cacheDir, { recursive: true });
      await fs.writeFile(this.cacheFilePath, JSON.stringify(this.cache, null, 2));
    } catch (error) {
      console.error("Failed to save cache:", error);
    }
  }

  /**
   * Gets the hash for a file
   */
  getHash(filePath: string): string | undefined {
    const normalizedPath = path.normalize(filePath);
    return this.cache[normalizedPath];
  }

  /**
   * Updates the hash for a file
   */
  async updateHash(filePath: string, hash: string): Promise<void> {
    const normalizedPath = path.normalize(filePath);
    this.cache[normalizedPath] = hash;
    // Auto-save after updates
    await this.saveCache();
  }

  /**
   * Deletes the hash for a file
   */
  async deleteHash(filePath: string): Promise<void> {
    const normalizedPath = path.normalize(filePath);
    delete this.cache[normalizedPath];
    await this.saveCache();
  }

  /**
   * Gets all cached hashes
   */
  getAllHashes(): Record<string, string> {
    return { ...this.cache };
  }

  /**
   * Clears the entire cache
   */
  async clearCache(): Promise<void> {
    this.cache = {};
    try {
      await fs.unlink(this.cacheFilePath);
    } catch (error) {
      // File might not exist, which is fine
    }
  }

  /**
   * Gets cache statistics
   */
  getStats(): { totalFiles: number; cacheFilePath: string } {
    return {
      totalFiles: Object.keys(this.cache).length,
      cacheFilePath: this.cacheFilePath,
    };
  }
}
